package com.party.course.util;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.hbga.xunpay.Xunpay;
import com.hbga.xunpay.XunpayClient;
import com.hbga.xunpay.exception.XunpayException;
import com.hbga.xunpay.model.*;
import com.hbga.xunpay.net.RequestOptions;
import com.hbga.xunpay.request.*;
import com.hbga.xunpay.response.*;
import com.party.business.domain.TOrder;
import com.party.course.domain.PayReqInfo;

import java.io.File;
import java.util.*;
import java.math.BigDecimal;
import java.util.stream.Collectors;

public class XunpayUtil {
    //商户号
    private static String mchNo = "M1752112514";
    //应用ID
    private static String appId = "686f1d82e4b02e1c8b4b5935";
    //秘钥
    private static String apiKey = "fPqfOo0sVJ31uvWZPH3iRvnNIkJDeW0bajMWaU7lJPvXNlA2RgI4E3TA68qstVd1YXeMYqH8zTra460UItPDcVZ8Kk6iPR1AgvpBQCSqIOa9rCsGeQ1vHi35jWXRPeTe";
    //支付方式
    private static String wayCode = "YEE_MP";
    //币种
    private static String currency = "CNY";
    //异步通知地址
    private static String notifyUrl = "http://kcsm.cqzwyt.cn/kcsm/webApi/callbackPay";
    private static String notifyUrl1 = "http://kcsm.cqzwyt.cn/kcsm/webApi/callbackTransparent";
    //发起支付请求客户端的IP地址
    private static String clientIp = "192.168.2.136";

    public static void main(String[] args) {
        TOrder order = new TOrder();
        order.setOrderNo("ORDER_20260618105658103");
        order.setTotalFee(1000000.00);
        order.setKcName("测试课程1");
        order.setRemark("测试课程啊啊啊啊啊1");
//        placeOrder(order);
//        closeOrder(order.getOrderNo());
//        selectOrder("ORDER_20250620150057061");
//
        List<ReceiverModel> list = new ArrayList<>();
        list.add(ReceiverModel.builder().ledgerNo("10091422110").amount("50").build());
//        list.add(ReceiverModel.builder().ledgerNo("10091422110").amount("20").build());
//        execOrder("ORDER_20250703173017361", list);

//        transparent("ORDER_20250704104620188");

    }

    /**
     * 初始化参数
     */
    public static XunpayClient init() {
        Xunpay.mchNo = mchNo;
        Xunpay.appId = appId;
        Xunpay.apiKey = apiKey;
        return XunpayClient.getInstance(Xunpay.appId, Xunpay.apiKey, Xunpay.getApiBase());
    }

    /**
     * 下单
     * 金额，单位分
     * @param order
     */
    public static PayReqInfo placeOrder(TOrder order) {
        XunpayClient xunpayClient = init();
        PayOrderCreateRequest request = new PayOrderCreateRequest();
        PayOrderCreateReqModel model = new PayOrderCreateReqModel();
        model.setMchNo(Xunpay.mchNo);                       // 商户号
        model.setAppId(xunpayClient.getAppId());            // 应用ID
        model.setWayCode(wayCode);                          // 支付方式
        model.setCurrency(currency);                           // 币种，目前只支持cny
        model.setClientIp(clientIp);                 // 发起支付请求客户端的IP地址
        model.setDivisionMode(Byte.valueOf("2"));
        String orderNo = "mho" + new Date().getTime();
        model.setMchOrderNo(order.getOrderNo());
        order.setTotalFee(order.getTotalFee());
        model.setAmount(convertYuanToCent(order.getTotalFee().toString())); // 金额，单位分
        model.setSubject(order.getKcName());                         // 商品标题
        model.setBody("学员" + order.getName() + "下单购买" + order.getKcName() + "课程");                            // 商品描述
        model.setNotifyUrl(notifyUrl);      // 异步通知地址
        model.setReturnUrl("");
        JSONObject obj = new JSONObject();
        obj.put("channelPayWay", "MINI_PROGRAM");
        obj.put("channelChannel", "WECHAT");
        model.setChannelExtra(obj.toString());       // 渠道扩展参数
        model.setExtParam("");                              // 商户扩展参数,回调时原样返回
        request.setBizModel(model);
        try {
            PayOrderCreateResponse response = xunpayClient.execute(request);
            System.out.printf("验签结果：{%s} \n", response.checkSign(Xunpay.apiKey));
            PayReqInfo reqInfo = PayReqInfo.builder()
                    .id(IdUtil.simpleUUID())
                    .orderNo(order.getOrderNo())
                    .reqUrl(request.getApiUri())
                    .type("0")
                    .param(JSON.toJSONString(model))
                    .repData(JSON.toJSONString(response))
                    .build();
            // 下单成功
            if (response.isSuccess(Xunpay.apiKey)) {
                PayOrderCreateResModel createResModel = response.get();
                reqInfo.setPayOrderId(response.get().getPayOrderId());
                System.out.printf("payOrderId：{%s} \n", createResModel.getPayOrderId());
                System.out.printf("mchOrderNo：{%s} \n", createResModel.getMchOrderNo());
                System.out.printf("getPayData：%s \n", createResModel.getPayData());
                System.out.printf("orderState：{%s} \n", createResModel.getOrderState());
            } else {
                System.out.printf("下单失败：{%s}\n", orderNo);
                System.out.printf("通道错误码：{%s}\n", response.getCode());
                System.out.printf("通道错误信息：{%s}\n", response.getMsg());
            }
            return reqInfo;
        } catch (XunpayException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据订单号 查询订单
     *
     * @param orderNo
     */
    public static PayReqInfo selectOrder(String orderNo) {
        XunpayClient xunpayClient = init();
        PayOrderQueryRequest request = new PayOrderQueryRequest();
        PayOrderQueryReqModel model = new PayOrderQueryReqModel();
        model.setMchNo(Xunpay.mchNo);                       // 商户号
        model.setAppId(xunpayClient.getAppId());            // 应用ID
        model.setMchOrderNo(orderNo);
        request.setBizModel(model);
        try {
            PayOrderQueryResponse response = xunpayClient.execute(request);
            System.out.printf("验签结果：{%s} \n", response.checkSign(Xunpay.apiKey));
            PayReqInfo reqInfo = PayReqInfo.builder()
                    .id(IdUtil.simpleUUID())
                    .orderNo(orderNo)
                    .reqUrl(request.getApiUri())
                    .type("1")
                    .param(JSON.toJSONString(model))
                    .repData(JSON.toJSONString(response))
                    .build();
            // 查询订单成功
            if (response.isSuccess(Xunpay.apiKey)) {
                PayOrderQueryResModel queryResModel = response.get();
                reqInfo.setPayOrderId(response.get().getPayOrderId());
                System.out.printf("getPayData：%s \n", queryResModel);
                System.out.printf("payOrderId：{%s} \n", queryResModel.getPayOrderId());
                System.out.printf("mchOrderNo：{%s} \n", queryResModel.getMchOrderNo());
                System.out.printf("orderState：{%s} \n", queryResModel.getState());
            } else {
                System.out.printf("下单失败：{%s}\n", orderNo);
                System.out.printf("通道错误码：{%s}\n", response.getCode());
                System.out.printf("通道错误信息：{%s}\n", response.getMsg());
            }
            return reqInfo;
        } catch (XunpayException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据订单号 关闭订单
     *
     * @param orderNo
     */
    public static PayReqInfo closeOrder(String orderNo) {
        XunpayClient xunpayClient = init();
        PayOrderCloseRequest request = new PayOrderCloseRequest();
        PayOrderCloseReqModel model = new PayOrderCloseReqModel();
        model.setMchNo(Xunpay.mchNo);                       // 商户号
        model.setAppId(xunpayClient.getAppId());               // 应用ID
        model.setMchOrderNo(orderNo);
        request.setBizModel(model);
        try {
            PayOrderCloseResponse response = xunpayClient.execute(request);
            System.out.printf("验签结果：{%s} \n", response.checkSign(Xunpay.apiKey));
            PayReqInfo reqInfo = PayReqInfo.builder()
                    .id(IdUtil.simpleUUID())
                    .orderNo(orderNo)
                    .reqUrl(request.getApiUri())
                    .type("2")
                    .param(JSON.toJSONString(model))
                    .repData(JSON.toJSONString(response))
                    .build();
            // 查询订单成功
            if (response.isSuccess(Xunpay.apiKey)) {
                PayOrderCloseResModel queryResModel = response.get();
                System.out.printf("code：%s \n", response.getCode());
                System.out.printf("msg：%s \n", response.getMsg());
                System.out.printf("data：%s \n", response.getData());
            } else {
                System.out.printf("关闭订单失败订单号：{%s}\n", orderNo);
                System.out.printf("通道错误码：{%s}\n", response.getCode());
                System.out.printf("通道错误信息：{%s}\n", response.getMsg());
            }
            return reqInfo;
        } catch (XunpayException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 分账
     * 金额，单位分
     * @param orderNo
     */
    public static PayReqInfo execOrder(String orderNo,List<ReceiverModel> list) {
        // 过滤 大于0 的数据
        list = list.stream().filter(model -> Double.valueOf(model.getAmount())> 0).collect(Collectors.toList());
        //todo 测试-统一处理提现金额为0.5元
//        for (ReceiverModel model : list) {
//            //金额换算
//            // 100*(1-0.06) =94
//            //公司：100*0.022  2.1
//            // 0.039
//            // 96.1-
//            String yAmount = model.getAmount(); //金额，单位元
//            Long fAmount = convertYuanToCent(yAmount);
//            model.setAmount(fAmount.toString());
//        }
        // list 中 相同商户号的金额合并
        // 合并相同ledgerNo的金额
        Map<String, Long> mergedAmounts = list.stream()
                .collect(Collectors.groupingBy(
                        ReceiverModel::getLedgerNo,
                        Collectors.summingLong(model -> convertYuanToCent(model.getAmount()))
                ));

       // 重新构建list，每个ledgerNo只保留一条记录
        List<ReceiverModel> mergedList = mergedAmounts.entrySet().stream()
                .map(entry -> ReceiverModel.builder()
                        .ledgerNo(entry.getKey())
                        .amount(entry.getValue().toString())
                        .build())
                .collect(Collectors.toList());

        list = mergedList;

        XunpayClient xunpayClient = init();
        PayOrderDivisionExecRequest request = new PayOrderDivisionExecRequest();
        PayOrderDivisionExecReqModel model = new PayOrderDivisionExecReqModel();
        model.setMchNo(Xunpay.mchNo);                       // 商户号
        model.setAppId(xunpayClient.getAppId());            // 应用ID
        model.setMchOrderNo(orderNo);
        model.setDivType("ledgerNo");
        model.setReceivers(JSON.toJSONString(list));
        request.setBizModel(model);
        System.out.println(JSON.toJSONString(model));
        try {
            PayOrderDivisionExecResponse response = xunpayClient.execute(request);
            System.out.printf("验签结果：{%s} \n", response.checkSign(Xunpay.apiKey));
            PayReqInfo reqInfo = PayReqInfo.builder()
                    .id(IdUtil.simpleUUID())
                    .orderNo(orderNo)
                    .reqUrl(request.getApiUri())
                    .type("4")
                    .param(JSON.toJSONString(model))
                    .repData(JSON.toJSONString(response))
                    .build();
            // 分账成功
            if (response.isSuccess(Xunpay.apiKey)) {
                PayOrderDivisionExecResModel queryResModel = response.get();
                System.out.printf("code：%s \n", response.getCode());
                System.out.printf("msg：%s \n", response.getMsg());
                System.out.printf("data：%s \n", response.getData());
            } else {
                System.out.printf("分账失败订单号：{%s}\n", orderNo);
                System.out.printf("通道错误码：{%s}\n", response.getCode());
                System.out.printf("通道错误信息：{%s}\n", response.getMsg());
            }
            return reqInfo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据订单号 完结分账
     * @param orderNo
     */
    public static void completeOrder(String orderNo) {
        XunpayClient xunpayClient = init();
        PayOrderDivisionCompleteRequest request = new PayOrderDivisionCompleteRequest();
        PayOrderDivisionCompleteReqModel model = new PayOrderDivisionCompleteReqModel();
        model.setMchNo(Xunpay.mchNo);                       // 商户号
        model.setAppId(xunpayClient.getAppId());            // 应用ID
        model.setMchOrderNo(orderNo);
        request.setBizModel(model);
        try {
            PayOrderDivisionExecResponse response = xunpayClient.execute(request);
            System.out.printf("验签结果：{%s} \n", response.checkSign(Xunpay.apiKey));
            // 分账成功
            if (response.isSuccess(Xunpay.apiKey)) {
                PayOrderDivisionExecResModel resModel = response.get();
                System.out.printf("code：%s \n", response.getCode());
                System.out.printf("msg：%s \n", response.getMsg());
                System.out.printf("data：%s \n", response.getData());
            } else {
                System.out.printf("完结分账失败订单号：{%s}\n", orderNo);
                System.out.printf("通道错误码：{%s}\n", response.getCode());
                System.out.printf("通道错误信息：{%s}\n", response.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    /**
     * 提现
     * 金额，单位元
     * @param orderNo
     */
    public static PayReqInfo transparent(String orderNo,BigDecimal changeAmount,String  merchantNo,String bankCardNo) {
        XunpayClient xunpayClient = init();
        ChannelTransparentRequest request = new ChannelTransparentRequest();
        ChannelTransparentReqModel model = new ChannelTransparentReqModel();
        model.setMchNo(Xunpay.mchNo);                       // 商户号
        model.setAppId(xunpayClient.getAppId());            // 应用ID
        model.setMchTransparentNo(orderNo);
        model.setNotifyUrl(notifyUrl1);
        model.setCtCode("yeepay_STX001");
        JSONObject obj = new JSONObject();
        obj.put("orderAmount", changeAmount); //提现金额单位元
//        obj.put("bankAccountNo", "6214832804615719");//提现到的银行卡号，需与易宝商户开户卡号一致
        obj.put("bankAccountNo",bankCardNo);//提现到的银行卡号，需与易宝商户开户卡号一致
        obj.put("receiveType", "REAL_TIME");//提现方式: REAL_TIME 实施到账
        obj.put("parentMerchantNo", "10091478670");//平台商的商编
//        obj.put("merchantNo", "10091676493");//提现账户的商编
        obj.put("merchantNo", merchantNo);//提现账户的商编

        model.setParams(obj.toJSONString());
        request.setBizModel(model);
        try {
            ChannelTransparentResponse response = xunpayClient.execute(request);
            System.out.printf("验签结果：{%s} \n", response.checkSign(Xunpay.apiKey));
            PayReqInfo reqInfo = PayReqInfo.builder()
                    .id(IdUtil.simpleUUID())
                    .orderNo(orderNo)
                    .reqUrl(request.getApiUri())
                    .type("5")
                    .param(JSON.toJSONString(model))
                    .repData(JSON.toJSONString(response))
                    .build();
            // 提现成功
            if (response.isSuccess(Xunpay.apiKey)) {
                ChannelTransparentResModel resModel = response.get();
                System.out.printf("code：%s \n", response.getCode());
                System.out.printf("msg：%s \n", response.getMsg());
                System.out.printf("data：%s \n", response.getData());
                JSONObject data = response.getData();
                // 解析data中的res字段，检查提现是否真正成功
                if (data != null && data.containsKey("res")) {
                    String resStr = data.getString("res");
                    if (resStr != null && !resStr.isEmpty()) {
                        com.alibaba.fastjson2.JSONObject resJson = JSON.parseObject(resStr);
                        String status = resJson.getString("status");
                        String returnCode = resJson.getString("returnCode");
                        String returnMsg = resJson.getString("returnMsg");
                        // 如果状态为FAIL或返回码不为成功，则抛出异常
                        if ("FAIL".equals(status)) {
                            String errorMsg = "提现失败: " + (returnMsg != null ? returnMsg : "未知错误");
                            System.out.println(errorMsg);
                            throw new RuntimeException(errorMsg);
                        }
                    }
                }

                System.out.println(data);
            } else {

                System.out.printf("提现失败订单号：{%s}\n", orderNo);
                System.out.printf("通道错误码：{%s}\n", response.getCode());
                System.out.printf("通道错误信息：{%s}\n", response.getMsg());
                throw new RuntimeException(response.getMsg());
            }
            return reqInfo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 将元换算成分
     *
     * @param amountInYuan 以元为单位的金额
     * @return 以分为单位的金额
     */
    public static Long convertYuanToCent(String amountInYuan) {
        BigDecimal amount = new BigDecimal(amountInYuan);
        return amount.multiply(new BigDecimal(100)).longValue();
    }
    public static Long convertYuanToCent(Double amountInYuan) {
        BigDecimal amount = new BigDecimal(amountInYuan);
        return amount.multiply(new BigDecimal(100)).longValue();
    }
    /**
     * 上传返回路径
     */
    public  static  String  uploadImage(String  path){

        String merQualUrl="";
        XunpayClient xunpayClient = init();
        ChannelTransparentMultipartRequest request = new ChannelTransparentMultipartRequest();
        ChannelTransparentReqModel model = new ChannelTransparentReqModel();
        // 设置请求参数
        model.setMchNo(Xunpay.mchNo); // 商户号
        model.setAppId(Xunpay.appId); // 应用ID
        model.setCtCode("yeepay_JJ001"); // 固定值
        model.setMchTransparentNo(IdUtil.simpleUUID()); // 商户生成的订单号
        request.setBizModel(model);
        // 设置上传文件
        Map<String, File> bizFiles = new HashMap<>();
        bizFiles.put("merQual", new File(path));
        request.setBizFiles(bizFiles);
        try {
            // 执行请求
            ChannelTransparentResponse response = xunpayClient.executeMultipart(request);
            System.out.println(com.alibaba.fastjson.JSON.toJSONString(response));
            System.out.println("验签结果： " + response.checkSign(Xunpay.apiKey));
            if (response.isSuccess(Xunpay.apiKey)) {
                Object dataObj = response.getData(); // 或者其他类似的方法名
                if (dataObj != null) {
                    // 将data对象也转换为JSON来处理
                    JSONObject dataJson = com.alibaba.fastjson.JSON.parseObject(com.alibaba.fastjson.JSON.toJSONString(dataObj));
                    String resStr = dataJson.getString("res");
                    if (resStr != null && !resStr.isEmpty()) {
                        JSONObject resJson = com.alibaba.fastjson.JSON.parseObject(resStr);
                        merQualUrl = resJson.getString("merQualUrl");
                        System.out.println("商户资质文件URL: " + merQualUrl);
                        System.out.println("返回代码: " + resJson.getString("returnCode"));
                        System.out.println("返回消息: " + resJson.getString("returnMsg"));
                        return merQualUrl;
                    }
                }
            } else {
                System.out.println("请求失败");
                return  "";
            }
        } catch (XunpayException e) {
            System.err.println("请求异常: " + e.getMessage());
            e.printStackTrace();
            return  "";
        }
        return  "";
    }
}

